<?php namespace simpleFlow\model;

use simpleFlow\Object as SFObject;
use simpleFlow\File as SFFile;
use simpleFlow\database\Connection as SFConnection;

/*CREATE SEQUENCE sq_user;
CREATE TABLE "user"
(
	id_user bigint DEFAULT nextval('sq_user'::regclass),
	tx_username character varying(12) NOT NULL,
	tx_password character varying(32) NOT NULL,
	CONSTRAINT user_pk PRIMARY KEY (id_user)
);*/

/**
 * Model classes
 * @package simpleFlow
 * @subpackage model
 * @author Guilherme Fontenele
 */
class Model extends SFObject
{
	/**
	 * @var SFConnection Connection 
	 */
	public static $objConnection;
	/**
	 * @var string Table name
	 */
	protected $_table;
	/**
	 * @var string Primary Key
	 * @todo Implements when the table have two or more PKs / TODO
	 */
	protected $_primaryKey;
	/**
	 * @var string Sequence name
	 */
	protected $_sequence;
	/**
	 * @var array Configs of model
	 */
	protected $_config;
	
	/**
	 * Constructor
	 */
	public function __construct()
	{
		self::$objConnection = new SFConnection();
		$this->readIniFile();
	}
	
	/**
	 * Read model.ini file
	 * @param string $strFile 
	 */
	public function readIniFile($strFile = null)
	{
		if(!$strFile)
		{
			$arrClass = \explode('\\', \get_class($this));
			if(\array_shift($arrClass) == 'simpleFlow' && \array_shift($arrClass) == 'app')
			{
				\array_pop($arrClass);
				$strFile = \implode('/',$arrClass).'/model.ini';
			}
		}
		if(SFFile::readable($strFile))
		{
			$arrParse = \parse_ini_file($strFile, true);
			$arrTable = $arrParse['_TABLE_'];
			unset($arrParse['_TABLE_']);

			$this->_table = $arrTable['table'];
			$this->_sequence = $arrTable['sequence'];
			foreach($arrParse as $_strFieldName => $_arrField)
			{
				$this->_config['database'][$_strFieldName] = $_arrField['name'];
				$this->_config['model'][$_arrField['name']] = $_strFieldName;
				$this->_config['_fields'][$_arrField['name']]['type'] = $_arrField['type'];
				$this->_config['_fields'][$_arrField['name']]['size'] = $_arrField['size'];
				if(isset($_arrField['not_null']))
				{
					$this->_config['_fields'][$_arrField['name']]['not_null'] = $_arrField['not_null'];
				}
				if(isset($_arrField['primary_key']))
				{
					$this->_primaryKey = $_strFieldName;
					$this->_config['_fields'][$_arrField['name']]['primary_key'] = $_arrField['primary_key'];
				}
			}
		}
	}
	
	/**
	 * Get Primary Key
	 * @return string Primary key name
	 */
	public function getKey()
	{
		if(isset($this->_config['database'][$this->_primaryKey]) && $strField = $this->_config['database'][$this->_primaryKey])
		{
			return $this->$strField;
		}else{
			return false;
		}
	}
	
	/**
	 * Read an item
	 * @param array $arrFilter Filter
	 */
	public function read($arrFilter)
	{
		if(\is_array($arrFilter))
		{
			$result = self::$objConnection->getLink()->query($this->__createSearchSql($arrFilter));
		}else{
			$result = self::$objConnection->getLink()->query($this->__createReadSql($arrFilter,'A'));
		}
		$this->db2model($result->fetch(\PDO::FETCH_ASSOC),$this);
	}
	
	/**
	 * Read all itens
	 * @param boolean $booParseObject If wants to parse objects
	 * @param integer $intPage Number of page
	 * @param integer $intOffset Number of offset
	 * @param string $strAlias Alias name
	 * @return array Results
	 */
	public function readAll($booParseObject = true,$intPage = null,$intOffset = SF_VIEW_LIST_ROWS,$strAlias = null)
	{
		$resResult = self::$objConnection->getLink()->query($this->__createReadAllSql($strAlias,$intPage,$intOffset));
		$arrResult = $resResult->fetchAll(\PDO::FETCH_ASSOC);
		
		if($booParseObject)
		{
			$strClass = \get_class($this);
			$_arrResult = $arrResult;
			$arrResult = array();
			foreach($_arrResult as $_arrTmp)
			{
				$objTemp = new $strClass;
				$arrResult[] = $this->db2model($_arrTmp,$objTemp);
				//TODO: tentar dar unset($objTemp) para liberar memória
			}
		}
		
		return $arrResult;
	}
	
	/**
	 * Save an item
	 */
	public function save()
	{
		self::$objConnection->getLink()->beginTransaction();
		if(!self::$objConnection->getLink()->exec($this->__createInsertSql()))
		{
			self::$objConnection->getLink()->rollBack();
			\trigger_error('Error on save '.get_class($this));
		}
		self::$objConnection->getLink()->commit();
	}
	
	/**
	 * Count itens
	 * @param string $strAlias Alias name
	 * @param integer $intPage Number of page
	 * @param integer $intOffset Number of offset
	 * @return integer Number of itens 
	 */
	public function count($strAlias = null,$intPage = null,$intOffset = null)
	{
		$resResult = self::$objConnection->getLink()->query($this->__createCountAllSql($strAlias,$intPage,$intOffset));
		$arrResult = $resResult->fetchAll(\PDO::FETCH_ASSOC);
		if(count($arrResult)) { return $arrResult[0]['total']; }
		else return 0;
	}
	
	/**
	 * Convert database results to model object
	 * @param array $arrRow Row
	 * @param Model $objModel Object
	 * @param boolean $booReturn If wants to return the object
	 * @return Model Object filled
	 */
	protected function db2model($arrRow,$objModel,$booReturn = true)
	{
		if(!$arrRow) { return false; }
		$_config = $objModel->_config['database'];
		foreach($arrRow as $_intKey => $_value)
		{
			$objModel->{$objModel->_config['database'][$_intKey]} = $_value;
		}
		if($booReturn) { return $objModel; }
	}
}

?>